package cn.bugstack.mybatis.builder.xml;

import cn.bugstack.mybatis.builder.BaseBuilder;
import cn.bugstack.mybatis.io.Resources;
import cn.bugstack.mybatis.mapping.MappedStatement;
import cn.bugstack.mybatis.mapping.SqlCommandType;
import cn.bugstack.mybatis.session.Configuration;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class XmlConfigBuilder extends BaseBuilder {

    private Element root;

    public XmlConfigBuilder(Reader reader) {
        super(new Configuration());
        // dom4j parse xml
        SAXReader saxReader = new SAXReader();
        try {
            Document document = saxReader.read(new InputSource(reader));
            root = document.getRootElement();
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }

    }

    public Configuration parse() throws Exception {
        Element mappers = root.element("mappers");
        List<Element> mapperList = mappers.elements("mapper");
        for (Element mapper : mapperList) {
            String resource = mapper.attributeValue("resource");
            // <mapper resource="mapper/User_Mapper.xml"/>
            Reader resourceAsReader = Resources.getResourceAsReader(resource);
            Document document = new SAXReader().read(resourceAsReader);
            Element root = document.getRootElement();
            String namespace = root.attributeValue("namespace");
            List<Element> selectList = root.elements("select");
            for (Element select : selectList) {
                String id = select.attributeValue("id");
                String parameterType = select.attributeValue("parameterType");
                String resultType = select.attributeValue("resultType");
                String sql = select.getText();

                // 将#{}替换为?
                Map<Integer, String> parameter = new HashMap<>();
                Pattern pattern = Pattern.compile("(#\\{(.*?)})");
                Matcher matcher = pattern.matcher(sql);
                for (int i = 1; matcher.find(); i++) {
                    String g1 = matcher.group(1); //#{id}
                    String g2 = matcher.group(2); //id
                    parameter.put(i, g2);
                    sql = sql.replace(g1, "?");
                }
                // select语句唯一标识
                String mappedStatementId = namespace + "." + id;
                String nodeName = select.getName();
                SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
                MappedStatement mappedStatement = new MappedStatement.Builder(mappedStatementId, sqlCommandType, parameterType, resultType, sql).build();
                // 添加解析完成的mappedStatement
                configuration.addMappedStatement(mappedStatement);
            }
            // 需要将mapper接口注册到MapperRegistry
            configuration.addMapper(Class.forName(namespace));
        }
        return configuration;
    }
}
